import winston from 'winston';
import 'winston-daily-rotate-file';
import path from 'path';
import fs from 'fs';
import dotenv from 'dotenv';

// 加载环境变量
const env = process.env.NODE_ENV || 'development';
const envFile = `.env.${env}`;
const defaultEnvFile = '.env';

// 先尝试加载指定环境的配置文件，如果不存在则加载默认.env文件
dotenv.config({ path: path.resolve(process.cwd(), envFile) });
dotenv.config({ path: path.resolve(process.cwd(), defaultEnvFile) });

// 日志目录
const LOG_DIR = path.join(process.cwd(), 'logs');

// 确保日志目录存在
if (!fs.existsSync(LOG_DIR)) {
  fs.mkdirSync(LOG_DIR, { recursive: true });
}

// 创建基础日志格式
const logFormat = winston.format.combine(
  winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
  winston.format.printf(({ level, message, timestamp, stack, category, ...meta }) => {
    let log = `${timestamp} ${level.toUpperCase()}`;
    
    // 添加类别信息（如果有）
    if (category) {
      log += ` [${category}]`;
    }
    
    log += `: ${message}`;
    
    // 添加堆栈信息（如果有）
    if (stack) {
      log += `\n${stack}`;
    }
    
    // 添加其他元数据（如果有）
    if (Object.keys(meta).length > 0) {
      log += `\n${JSON.stringify(meta, null, 2)}`;
    }
    
    return log;
  })
);

// 创建控制台日志格式（带颜色）
const consoleFormat = winston.format.combine(
  winston.format.colorize(),
  winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
  winston.format.printf(({ level, message, timestamp, stack, category, ...meta }) => {
    let log = `${timestamp} ${level}`;
    
    if (category) {
      log += ` [${category}]`;
    }
    
    log += `: ${message}`;
    
    if (stack) {
      log += `\n${stack}`;
    }
    
    if (Object.keys(meta).length > 0) {
      log += `\n${JSON.stringify(meta, null, 2)}`;
    }
    
    return log;
  })
);

/**
 * 日志记录器配置选项
 */
export interface LoggerOptions {
  /** 是否在控制台输出日志 */
  console?: boolean;
  /** 是否写入日志文件 */
  file?: boolean;
  /** 是否创建错误日志文件 */
  errorFile?: boolean;
  /** 是否使用单个文件（不按日期滚动） */
  singleFile?: boolean;
  /** 日志文件名（不包含路径和扩展名） */
  filename?: string;
  /** 日志文件大小限制 */
  maxSize?: string;
  /** 日志文件保留时间/数量 */
  maxFiles?: string;
  /** 是否启用日志压缩 */
  zippedArchive?: boolean;
  /** 日志级别 */
  level?: string;
  /** 日期格式（用于文件名） */
  datePattern?: string;
}

// 创建日志实例缓存
const loggers: Record<string, winston.Logger> = {};
// 创建日志实例配置缓存，用于判断是否需要重新创建日志记录器
const loggerConfigs: Record<string, string> = {};

/**
 * 获取日志记录器
 * @param category 日志类别，默认为'default'
 * @param options 日志配置选项
 * @returns 日志记录器
 */
export function getLogger(category: string = 'default', options?: LoggerOptions): winston.Logger {
  // 合并默认配置和自定义配置
  const config: LoggerOptions = {
    console: true, // 是否在控制台输出日志
    file: true, // 是否写入日志文件
    errorFile: true, // 是否创建错误日志文件
    singleFile: false, // 是否使用单个文件（不按日期滚动）
    filename: category, // 日志文件名（不包含路径和扩展名）
    maxSize: process.env.LOG_MAX_SIZE || '20m', // 日志文件大小限制
    maxFiles: process.env.LOG_MAX_FILES || '14d', // 日志文件保留时间/数量
    zippedArchive: true, // 是否启用日志压缩
    level: process.env.LOG_LEVEL || (process.env.NODE_ENV === 'production' ? 'info' : 'debug'), // 日志级别
    datePattern: 'YYYY-MM-DD', // 日期格式（用于文件名）
    ...options
  };
  
  // 将配置对象转换为字符串，用于比较配置是否变化
  const configStr = JSON.stringify(config);
  
  // 如果已存在该类别的日志记录器，且配置没有变化，直接返回
  if (loggers[category] && loggerConfigs[category] === configStr) {
    return loggers[category];
  }
  
  // 创建transports数组
  const transports: winston.transport[] = [];
  
  // 添加控制台输出（如果启用）
  if (config.console) {
    transports.push(
      new winston.transports.Console({
        format: consoleFormat
      })
    );
  }
  
  // 添加文件输出（如果启用）
  if (config.file) {
    // 确定文件路径
    let logFilePath: string;
    
    if (config.singleFile) {
      // 使用单个文件
      logFilePath = path.join(LOG_DIR, `${config.filename}.log`);
      
      transports.push(
        new winston.transports.File({
          filename: logFilePath,
          maxsize: parseInt(config.maxSize!) * 1024 * 1024, // 将MB转换为字节
          maxFiles: parseInt(config.maxFiles!),
          tailable: true,
          zippedArchive: config.zippedArchive,
          level: config.level
        })
      );
    } else {
      // 使用按日期滚动的文件
      logFilePath = path.join(LOG_DIR, `${config.filename}-%DATE%.log`);
      
      transports.push(
        new winston.transports.DailyRotateFile({
          filename: logFilePath,
          datePattern: config.datePattern,
          zippedArchive: config.zippedArchive,
          maxSize: config.maxSize,
          maxFiles: config.maxFiles,
          level: config.level
        })
      );
    }
  }
  
  // 添加错误日志文件（如果启用）
  if (config.errorFile && config.file && !config.singleFile) {
    const errorLogFilePath = path.join(LOG_DIR, `${config.filename}-error-%DATE%.log`);
    
    transports.push(
      new winston.transports.DailyRotateFile({
        filename: errorLogFilePath,
        datePattern: config.datePattern,
        zippedArchive: config.zippedArchive,
        maxSize: process.env.LOG_ERROR_MAX_SIZE || config.maxSize,
        maxFiles: process.env.LOG_ERROR_MAX_FILES || config.maxFiles,
        level: 'error'
      })
    );
  }
  
  // 创建日志记录器
  const logger = winston.createLogger({
    level: config.level,
    format: logFormat,
    defaultMeta: { category },
    transports
  });
  
  // 缓存日志记录器和配置
  loggers[category] = logger;
  loggerConfigs[category] = configStr;
  
  return logger;
}

// 默认日志记录器
const defaultLogger = getLogger('default');

// 导出默认日志记录器和获取日志记录器的方法
export default defaultLogger;